﻿using System;
using System.Drawing;
using System.Drawing.Text;
using System.Windows.Forms;
using CloudShot.Utils;

namespace CloudShot.States
{
	class ShotState : IShotState
	{
		protected readonly Form Owner;
		private readonly Pen _borderPen = new Pen(Color.FromArgb(100, 100, 100), 1);
		private bool _pressed;
		private bool _ctrlPressed;
		private Point _start;
		private Point _end;
		private readonly Bitmap _lightBitmap;
		private readonly Bitmap _darkBitmap;

		public ShotState(Form owner)
		{
			Owner = owner;

			_lightBitmap = new Bitmap(Owner.BackgroundImage);
			_darkBitmap = new Bitmap(_lightBitmap);

			using (Graphics g = Graphics.FromImage(_darkBitmap))
			using (SolidBrush fillBrush = new SolidBrush(Color.FromArgb(190, Color.Black)))
			{
				g.FillRectangle(fillBrush, 0, 0, _darkBitmap.Width, _darkBitmap.Height);
			}

			Owner.BackgroundImage = _darkBitmap;

			owner.KeyDown += OnKeyDown;
			owner.KeyUp += OnKeyDown;
		}

		protected void DrawTextLabel(string label, Point pos, Graphics graphics, bool onRightSide)
		{
			SizeF labelSize = TextRenderer.MeasureText(label, Owner.Font);

			int x;

			if (onRightSide)
				x = (pos.X + labelSize.Width < Owner.Width) ? pos.X : pos.X - (int)labelSize.Width;
			else
				x = Math.Max(pos.X - (int)labelSize.Width, 0);

			int y = (pos.Y + labelSize.Height < Owner.Height) ? pos.Y : pos.Y - (int)labelSize.Height;

			if ((pos.Y > y) && (pos.X + labelSize.Width < Owner.Width))
				x = pos.X;

			Rectangle labelRect = new Rectangle(x, y, (int)labelSize.Width, (int)labelSize.Height);
			TextRenderer.DrawText(graphics, label, Owner.Font, labelRect, Color.Black, Color.WhiteSmoke);
		}

		private void OnKeyDown(object sender, KeyEventArgs e)
		{
			_ctrlPressed = e.Control;
			Owner.Invalidate();
		}

		public void Paint(Graphics graphics)
		{
			_end = Owner.PointToClient(Cursor.Position);
            
			if (!_pressed)
			{
				Screen currentScreen = Screen.FromPoint(Cursor.Position);
				string label = string.Format(" {0} x {1}", Cursor.Position.X - currentScreen.Bounds.X, Cursor.Position.Y - currentScreen.Bounds.Y);

				DrawTextLabel(label, _end, graphics, true);

				if (_ctrlPressed)
				{
					//draw cross
					DrawCross(graphics);
				}


				Font font = new Font(Owner.Font.FontFamily, 15f);
				TextRenderer.DrawText(graphics, _typedText, font, Owner.RectangleToClient(currentScreen.Bounds), Color.WhiteSmoke, TextFormatFlags.WordBreak | TextFormatFlags.HorizontalCenter);
			}
			else
			{
				Rectangle rect = CalculateRegion(_start, _end);

				if (rect.Width > 0 && rect.Height > 0)
				{
					graphics.DrawImage(_lightBitmap, rect.X, rect.Y, rect, GraphicsUnit.Pixel);
					DrawTypedText(graphics, rect);
					graphics.DrawRectangle(_borderPen, rect);


					//Text label
					string label = string.Format(" {0} x {1}", rect.Width, rect.Height);
					DrawTextLabel(label, new Point(rect.Right, rect.Bottom), graphics, false);
				}
			}
		}

		private void DrawTypedText(Graphics graphics, Rectangle rect)
		{
			graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
			//calculating
			Font font = new Font(Owner.Font.FontFamily, 11f, FontStyle.Regular);
			SizeF size = TextRenderer.MeasureText(_typedText, font, rect.Size, TextFormatFlags.WordBreak);
			Rectangle textRect = new Rectangle(rect.X, rect.Bottom - (int)size.Height, rect.Width, (int)size.Height);

			//drawing
			//graphics.FillRectangle(new SolidBrush(Color.FromArgb(150, Color.WhiteSmoke)), textRect);
			//TextRenderer.DrawText(graphics, _typedText, font, textRect, Color.Black, TextFormatFlags.WordBreak);
			graphics.FillRectangle(new SolidBrush(Color.FromArgb(200, Color.Black)), textRect);
			TextRenderer.DrawText(graphics, _typedText, font, textRect, Color.WhiteSmoke, TextFormatFlags.WordBreak | TextFormatFlags.HorizontalCenter);
		}

		private void DrawCross(Graphics graphics)
		{
			using (Pen pen = new Pen(Color.FromArgb(180, Color.Gray)))
			{
				Point pos = Owner.PointToClient(Cursor.Position);
				graphics.DrawLine(pen, pos.X, 0, pos.X, Owner.Height);
				graphics.DrawLine(pen, 0, pos.Y, Owner.Width, pos.Y);
			}
		}

		public void Start(Point location)
		{
			_start = location;
			_pressed = true;
		}

		public virtual void Update(Point location)
		{
		}

		public void End()
		{
			_pressed = false;
		}

		public Image Shot()
		{
			Rectangle shotRect = Rectangle.Empty;

		/*	if (_start == _end)
			{
				//get window shot
				Point screenPoint = Owner.PointToScreen(_start);
				WindowInfo window = _windowManager.GetWindowRectFromPoint(screenPoint, new IntPtr[] { Owner.Handle });

				if (window != null)
				{
					//if window is greater screen, we must crop window by screen size
					//window.Bounds.Intersect( Owner.DesktopBounds );
					shotRect = Owner.RectangleToClient(window.Bounds);
					shotRect.Intersect(Owner.RectangleToClient(Owner.Bounds));

				}
			}
			else*/
			{
				//get region shot
				shotRect = CalculateRegion(_start, _end);
			}

			return Shot(shotRect);
		}

		protected Image Shot(Rectangle rect)
		{
			if (rect.Width <= 0 || rect.Height <= 0 || rect.X < 0 || rect.Y < 0)
				return null;

			Bitmap bmpCrop = _lightBitmap.Clone(rect, _lightBitmap.PixelFormat);

			using (Graphics g = Graphics.FromImage(bmpCrop))
			{
				DrawTypedText(g, new Rectangle(0, 0, rect.Width, rect.Height));
			}

			return bmpCrop;
		}

		private static Rectangle CalculateRegion(Point start, Point end)
		{
			Rectangle result = new Rectangle();

			result.X = Math.Min(start.X, end.X);
			result.Width = Math.Abs(start.X - end.X);

			result.Y = Math.Min(start.Y, end.Y);
			result.Height = Math.Abs(start.Y - end.Y);

			return result;
		}

		private string _typedText = string.Empty;
		public void Type(string text)
		{
			_typedText = text;
		}
	}
}
